/// 聊天Provider
/// 管理聊天消息和对话
library;
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:chat_project/models/message_model.dart';
import 'package:chat_project/models/conversation_model.dart';
import 'package:chat_project/models/user_model.dart';
import 'package:chat_project/services/api_service.dart';
import 'package:chat_project/services/socket_service.dart';

class ChatProvider with ChangeNotifier {
  final ApiService _apiService = ApiService();
  final SocketService _socketService = SocketService();
  
  List<Conversation> _conversations = [];
  final Map<String, List<Message>> _messages = {}; // 用户ID -> 消息列表
  final Map<String, bool> _typingStatus = {}; // 用户ID -> 输入状态
  
  String? _selectedConversationId;
  String? _selectedUserId;
  bool _isLoading = false;
  String? _error;
  Timer? _periodicRefreshTimer; // 定期刷新计时器
  
  // Getters
  List<Conversation> get conversations => _conversations;
  String? get selectedConversationId => _selectedConversationId;
  String? get selectedUserId => _selectedUserId;
  bool get isLoading => _isLoading;
  String? get error => _error;
  bool get hasSelectedConversation => _selectedConversationId != null;
  bool get socketConnected => _socketService.isConnected;
  
  // 获取指定用户的消息列表
  List<Message> getMessages(String userId) {
    return _messages[userId] ?? [];
  }
  
  // 获取用户输入状态
  bool isUserTyping(String userId) {
    return _typingStatus[userId] ?? false;
  }
  
  // 初始化
  Future<void> init(User currentUser) async {
    // 停止之前的计时器
    _cancelRefreshTimer();
    
    // 初始化Socket连接
    await _socketService.init();
    
    // 注册Socket事件监听
    _registerSocketEvents(currentUser);
    
    // 加载对话列表
    await loadConversations();
    
    // 设置定期刷新
    _startPeriodicRefresh();
  }
  
  // 设置定期刷新机制
  void _startPeriodicRefresh() {
    _cancelRefreshTimer();
    
    // 每30秒检查一次，确保消息是最新的
    _periodicRefreshTimer = Timer.periodic(const Duration(seconds: 30), (timer) async {
      // 重新连接Socket
      if (!_socketService.isConnected) {
        _socketService.reconnect();
      }
      
      // 如果有选中的对话，刷新消息
      if (_selectedUserId != null) {
        try {
          await loadMessages(_selectedUserId!);
        } catch (e) {
          print('定期刷新消息失败: $e');
        }
      }
      
      // 刷新对话列表
      try {
        await loadConversations();
      } catch (e) {
        print('定期刷新对话列表失败: $e');
      }
    });
  }
  
  // 取消定期刷新计时器
  void _cancelRefreshTimer() {
    _periodicRefreshTimer?.cancel();
    _periodicRefreshTimer = null;
  }
  
  // 注册Socket事件
  void _registerSocketEvents(User currentUser) {
    // 先清除之前的所有监听器，避免重复监听
    _socketService.off('connect');
    _socketService.off('connect_error');
    _socketService.off('receive_message');
    _socketService.off('message_status_update');
    _socketService.off('typing:start');
    _socketService.off('typing:stop');
    _socketService.off('user:online');
    _socketService.off('user:offline');
    
    // 连接成功事件
    _socketService.on('connect', (_) {
      print('聊天提供者：Socket连接成功');
      // 重新加载数据
      loadConversations();
      if (_selectedUserId != null) {
        loadMessages(_selectedUserId!);
      }
    });
    
    // 连接错误事件
    _socketService.on('connect_error', (error) {
      print('聊天提供者：Socket连接错误 - $error');
    });
    
    // 接收新消息
    _socketService.on('receive_message', (data) {
      if (data == null) return;
      
      try {
        print('接收到新消息事件: $data');
        final message = Message.fromJson(data as Map<String, dynamic>);
        
        // 确保发送者ID是字符串形式
        final String senderId;
        if (message.sender.id.contains('{') || message.sender.id.contains('}')) {
          // 从复杂对象中提取ID
          final idMatch = RegExp(r"_id:\s*([^\s,}]+)").firstMatch(message.sender.id);
          if (idMatch != null && idMatch.groupCount > 0) {
            senderId = idMatch.group(1)!.trim();
          } else {
            senderId = message.sender.id;
          }
        } else {
          senderId = message.sender.id;
        }
        
        // 检查消息是否已存在，更全面的去重逻辑
        final messageId = message.id;
        bool messageExists = false;
        
        if (_messages.containsKey(senderId)) {
          // 检查完全匹配的ID
          messageExists = _messages[senderId]!.any((m) => m.id == messageId);
          
          // 检查临时ID与真实ID的对应关系
          if (!messageExists && messageId.startsWith('temp_')) {
            // 如果是临时ID，我们检查内容和时间来确定是否是重复消息
            messageExists = _messages[senderId]!.any((m) => 
              m.content == message.content && 
              m.createdAt.difference(message.createdAt).inSeconds.abs() < 5);
          }
          
          // 如果消息ID不是temp开头，检查是否有对应的临时消息需要替换
          if (!messageExists && !messageId.startsWith('temp_')) {
            final tempIndex = _messages[senderId]!.indexWhere((m) => 
              m.id.startsWith('temp_') && 
              m.content == message.content &&
              m.createdAt.difference(message.createdAt).inSeconds.abs() < 10);
              
            if (tempIndex != -1) {
              // 找到匹配的临时消息，替换它
              _messages[senderId]![tempIndex] = message;
              
              // 强制通知UI更新
              _forceNotifyListeners();
              
              // 如果当前正在查看该对话，确保消息已读
              if (senderId == _selectedUserId) {
                _socketService.markMessageAsRead(message.id);
              }
              
              return; // 直接返回，避免重复添加
            }
          }
        }
        
        // 只有当消息确实不存在时才添加
        if (!messageExists) {
          print('添加新消息: $messageId, 发送者: $senderId');
          // 添加消息到列表
          if (!_messages.containsKey(senderId)) {
            _messages[senderId] = [];
          }
          _messages[senderId]?.add(message);
          
          // 更新对话列表中的最后一条消息
          _updateConversationLastMessage(senderId, message);
          
          // 如果当前正在查看该对话，则标记为已读
          if (senderId == _selectedUserId) {
            _socketService.markMessageAsRead(message.id);
          } else {
            // 如果不是当前对话，增加未读消息计数
            final convIndex = _conversations.indexWhere((c) => c.contact.id == senderId);
            if (convIndex != -1) {
              final conv = _conversations[convIndex];
              _conversations[convIndex] = conv.copyWith(
                unreadCount: conv.unreadCount + 1
              );
            }
          }
          
          // 强制通知所有监听器
          _forceNotifyListeners();
        } else {
          print('忽略重复消息: $messageId');
        }
      } catch (e) {
        print('解析接收消息错误: $e');
      }
    });
    
    // 消息状态更新
    _socketService.on('message_status_update', (data) {
      if (data == null) return;
      
      try {
        final messageId = data['messageId'];
        final status = data['status'];
        
        // 更新消息状态
        for (final userId in _messages.keys) {
          final messageList = _messages[userId];
          final index = messageList?.indexWhere((m) => m.id == messageId) ?? -1;
          
          if (index != -1 && messageList != null) {
            final oldMessage = messageList[index];
            final statusEnum = status == 'read' 
                ? MessageStatus.read 
                : (status == 'delivered' ? MessageStatus.delivered : MessageStatus.sent);
            
            final updatedMessage = oldMessage.copyWith(
              status: statusEnum,
              readAt: data['readAt'] != null ? DateTime.parse(data['readAt']) : null
            );
            
            messageList[index] = updatedMessage;
            
            _forceNotifyListeners();
            break;
          }
        }
      } catch (e) {
        print('处理消息状态更新错误: $e');
      }
    });
    
    // 用户输入状态开始
    _socketService.on('typing:start', (data) {
      if (data == null) return;
      
      try {
        print('收到用户开始输入事件: $data');
        final userId = data['userId'];
        
        if (userId != null) {
          _typingStatus[userId] = true;
          _forceNotifyListeners();
        }
      } catch (e) {
        print('处理用户输入状态开始错误: $e');
      }
    });
    
    // 用户输入状态结束
    _socketService.on('typing:stop', (data) {
      if (data == null) return;
      
      try {
        print('收到用户停止输入事件: $data');
        final userId = data['userId'];
        
        if (userId != null) {
          _typingStatus[userId] = false;
          _forceNotifyListeners();
        }
      } catch (e) {
        print('处理用户输入状态结束错误: $e');
      }
    });
    
    // 用户在线状态变化
    _socketService.on('user:online', (data) {
      if (data == null) return;
      
      try {
        final userId = data['userId'];
        if (userId == null) return;
        
        // 更新对话列表中的用户在线状态
        for (var i = 0; i < _conversations.length; i++) {
          if (_conversations[i].contact.id == userId) {
            final updatedContact = _conversations[i].contact.copyWith(
              isOnline: true,
              lastSeen: DateTime.now()
            );
            
            _conversations[i] = _conversations[i].copyWith(contact: updatedContact);
            break;
          }
        }
        
        _forceNotifyListeners();
      } catch (e) {
        print('处理用户在线状态错误: $e');
      }
    });
    
    // 用户离线状态变化
    _socketService.on('user:offline', (data) {
      if (data == null) return;
      
      try {
        final userId = data['userId'];
        if (userId == null) return;
        
        // 更新对话列表中的用户在线状态
        for (var i = 0; i < _conversations.length; i++) {
          if (_conversations[i].contact.id == userId) {
            final updatedContact = _conversations[i].contact.copyWith(
              isOnline: false,
              lastSeen: DateTime.now()
            );
            
            _conversations[i] = _conversations[i].copyWith(contact: updatedContact);
            break;
          }
        }
        
        _forceNotifyListeners();
      } catch (e) {
        print('处理用户离线状态错误: $e');
      }
    });
  }
  
  // 强制通知所有监听器更新
  void _forceNotifyListeners() {
    try {
      // 立即通知
      notifyListeners();
      
      // 为了确保UI能显示最新消息，加一个微小延迟后再次通知
      Future.delayed(const Duration(milliseconds: 50), () {
        notifyListeners();
      });
      
      // 再次延迟通知，确保UI处理完成（有些设备可能需要更长时间）
      Future.delayed(const Duration(milliseconds: 300), () {
        notifyListeners();
      });
    } catch (e) {
      print('通知监听器失败: $e');
    }
  }
  
  // 加载对话列表
  Future<void> loadConversations() async {
    try {
      _isLoading = true;
      _error = null;
      notifyListeners();
      
      final response = await _apiService.getConversations();
      
      // 使用异步方法加载对话列表
      final List<Conversation> loadedConversations = [];
      for (var conv in response) {
        try {
          final conversation = await Conversation.fromJsonAsync(conv);
          loadedConversations.add(conversation);
        } catch (e) {
          print('加载单个对话失败: $e');
        }
      }
      
      _conversations = loadedConversations;
      
      _isLoading = false;
      notifyListeners();
    } catch (e) {
      _isLoading = false;
      _error = e.toString();
      notifyListeners();
    }
  }
  
  // 选择对话
  Future<void> selectConversation(String conversationId, String userId) async {
    if (userId.isEmpty) {
      print('警告: selectConversation收到空的userId');
      return;
    }
    
    // 确保只使用字符串形式的ID
    final String safeUserId = userId;
    
    print('选择对话: conversationId=$conversationId, userId=$safeUserId');
    _selectedConversationId = conversationId;
    _selectedUserId = safeUserId;
    notifyListeners();
    
    // 加载消息记录
    await loadMessages(safeUserId, conversationId: conversationId);
    
    // 标记对话为已读
    await markConversationAsRead(conversationId);
  }
  
  // 清除选择的对话
  void clearSelectedConversation() {
    _selectedConversationId = null;
    _selectedUserId = null;
    notifyListeners();
  }
  
  // 加载消息历史
  Future<void> loadMessages(String userId, {String? conversationId}) async {
    if (userId.isEmpty) {
      print('警告: loadMessages收到空的userId');
      return;
    }
    
    try {
      print('加载消息历史: userId=$userId, conversationId=$conversationId');
      _isLoading = true;
      notifyListeners();
      
      final messages = await _apiService.getMessages(
        userId, 
        conversationId: conversationId ?? _selectedConversationId
      );
      
      // 转换消息数据
      _messages[userId] = messages.map((data) => Message.fromJson(data)).toList();
      
      notifyListeners();
    } catch (e) {
      print('加载消息历史失败: $e');
      // 设置空消息列表以避免null错误
      _messages[userId] = [];
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }
  
  // 发送消息
  Future<void> sendMessage(String content, User sender, {String type = 'text'}) async {
    if (_selectedUserId == null || _selectedConversationId == null) {
      print('发送消息失败: 未选择对话');
      return;
    }
    
    if (_selectedUserId!.isEmpty) {
      print('发送消息失败: 选择的用户ID为空');
      return;
    }
    
    // 确保_selectedUserId是字符串
    final String safeReceiverId = _selectedUserId.toString();
    final String? safeConversationId = _selectedConversationId;
    
    try {
      print('发送消息: content=$content, receiver=$safeReceiverId, conversationId=$safeConversationId, type=$type');
      
      // 创建临时消息对象，用于立即显示在UI上
      final tempId = 'temp_${DateTime.now().millisecondsSinceEpoch}';
      final tempMessage = Message(
        id: tempId,
        content: content,
        type: type == 'text' ? MessageType.text : MessageType.image,
        sender: sender,
        receiverId: safeReceiverId,
        status: MessageStatus.sent,
        createdAt: DateTime.now(),
      );
      
      // 添加到消息列表
      if (!_messages.containsKey(safeReceiverId)) {
        _messages[safeReceiverId] = [];
      }
      _messages[safeReceiverId]?.add(tempMessage);
      
      // 更新对话列表中的最后一条消息
      _updateConversationLastMessage(safeReceiverId, tempMessage);
      
      notifyListeners();
      
      // 使用API发送消息，而不是通过Socket发送
      // 避免Socket和API同时发送导致的重复问题
      final response = await _apiService.sendMessage(
        safeReceiverId,
        content,
        type,
        conversationId: safeConversationId,
      );
      
      // 处理API响应，更新临时消息
      final newMessage = Message.fromJson(response);
      
      // 替换临时消息
      final index = _messages[safeReceiverId]?.indexWhere((m) => m.id == tempId) ?? -1;
      if (index != -1 && _messages[safeReceiverId] != null) {
        _messages[safeReceiverId]![index] = newMessage;
      }
      
      // 检查该用户是否已在会话列表中
      final conversationExists = _conversations.any((conv) => conv.contact.id == safeReceiverId);
      
      // 如果不存在，重新加载会话列表
      if (!conversationExists) {
        print('对话不存在，重新加载会话列表');
        await loadConversations();
      } else {
        // 更新对话列表中的最后一条消息
        _updateConversationLastMessage(safeReceiverId, newMessage);
      }
      
      notifyListeners();
    } catch (e) {
      print('发送消息失败: $e');
      
      // 更新临时消息状态为发送失败
      final index = _messages[safeReceiverId]?.indexWhere(
        (m) => m.id.startsWith('temp_')
      ) ?? -1;
      
      if (index != -1 && _messages[safeReceiverId] != null) {
        final failedMessage = _messages[safeReceiverId]![index].copyWith(
          status: MessageStatus.sent
        );
        _messages[safeReceiverId]![index] = failedMessage;
        
        notifyListeners();
      }
    }
  }
  
  // 更新对话列表中的最后一条消息
  void _updateConversationLastMessage(String userId, Message message) {
    final index = _conversations.indexWhere((conv) => conv.contact.id == userId);
    
    if (index != -1) {
      _conversations[index] = _conversations[index].copyWith(
        lastMessage: message,
        updatedAt: DateTime.now(),
      );
      
      // 将该对话移到列表顶部
      if (index > 0) {
        final conversation = _conversations.removeAt(index);
        _conversations.insert(0, conversation);
      }
    }
  }
  
  // 标记对话为已读
  Future<void> markConversationAsRead(String conversationId) async {
    try {
      // 从列表中找到对话，将未读数设为0
      final index = _conversations.indexWhere((conv) => conv.id == conversationId);
      
      if (index != -1) {
        _conversations[index] = _conversations[index].copyWith(unreadCount: 0);
        notifyListeners();
      }
      
      // 调用API
      await _apiService.markConversationAsRead(conversationId);
    } catch (e) {
      print('标记对话已读错误: $e');
    }
  }
  
  // 发送正在输入状态  
  void sendTypingStatus(bool isTyping) {    
    if (_selectedUserId == null) return;        
    
    print('发送输入状态: userId=$_selectedUserId, isTyping=$isTyping');    
    _socketService.sendTyping(_selectedUserId!, isTyping);  
  }
  
  // 重新连接Socket
  void reconnectSocket() {
    _socketService.reconnect();
  }
  
  // 清理资源
  @override
  void dispose() {
    _socketService.disconnect();
    super.dispose();
  }
}
